/*
 * GeographicalCoordinates.java
 *
 * Created on Antradienis, 2006, Spalio 3, 10.52
 *
 */

package org.mif.mobp.core.coord;
import java.util.Date;
/**
 * Klase realizuoja darba su koordinatemis
 */
public class GeographicalCoordinates extends Coordinates {
    
    public int       latitudeInt,
                     longitudeInt;
    public double    latitude,
                     longitude,
                     height;
    public String    latitudeS,
                     longitudeS;
    
    /** Creates a new instance of GeographicalCoordinates */
    public GeographicalCoordinates() {
        super();
    }
    
    public GeographicalCoordinates (Date d, int b) {
        super (d, b);
    }
    
    public GeographicalCoordinates (int lai, double la, String las,
                                    int loi, double lo, String los) 
    {
        this (new Date(), 10, lai, la, las, loi, lo, los);
    }
    
    /** Sukuria koordinaciu objecta su tam tikrais parametrais
     * @param d koordinates gavimo data
     * @param b paklaida
     * @param lai latitude laipsniai
     * @param la latitude minutes
     * @param las latitude Stringas (N arba S)
     * @param loi longitude laipsniai
     * @param lo longitude minutes
     * @param los longitude Stringas (E arba W)
     */
    public GeographicalCoordinates (Date d, int b, 
                                    int lai, double la, String las,
                                    int loi, double lo, String los) 
    {
        super (d, b);
        latitudeInt = lai;
        latitude = la;
        latitudeS = las;
        
        longitudeInt = loi;
        longitude = lo;
        longitudeS = los;
    }
    
    /** Grazina koordinaciu israiska laipsniais
     * t.y. pavercia koordinates is laipsniu ir minuciu
     * vien i laipsnius
     * latitude  neigiama, kai S;
     * longitude neigiama, kai E
     * @return double masyvas {lat, long}
     */
    public double[] inDegree(){
        double[] coord = new double[2];
        
        coord[0]=(double)((double)latitudeInt + latitude / 60.0);
        if (latitudeS.compareTo("S")==0)
            coord[0] *= -1;
        coord[1]=(double)((double)longitudeInt + longitude / 60.0);
        if (longitudeS.compareTo("E")==0)
            coord[1] *= -1;
        
        return coord;    
    }
    
    /** Nustato koordinates
     *  @param lat - platuma laipsniais
     *  @param lon - ilguma laipsniais
     */
    // TODO: min/max kontrole...
    public void setDegrees(double lat, double lon){
//        System.out.println("GOT: " + lat + " ^ " + lon);
        if(lat>0)
            latitudeS="N";
        else{
            latitudeS="S";
            lat *= -1;
        }
        latitudeInt = (int)lat;
//        System.out.println("latitudeInt: " + latitudeInt);
        latitude=(lat-latitudeInt)*60;
//        System.out.println("latitude: " + latitude);        
//        System.out.println("latitudeS " + latitudeS);
        
        if(lon>0)
            longitudeS="W";
        else{
            longitudeS="E";
            lon *= -1;
//            System.out.println("!!!!!!!new lon: " + lon);
        }
        longitudeInt= (int)lon;
//        System.out.println("lonInt: " + longitudeInt);
        longitude=(lon-longitudeInt)*60;
//        System.out.println("long: " + longitude);
        
//        System.out.println("lons: " + longitudeS);
    }

    public String toString() {
        return new String (latitudeInt + " " + latitude + " " + latitudeS + " " +
                longitudeInt + " " + longitude + " " + longitudeS);
    }
    
    /**Grazina atstuma metrais nuo shis koordinates iki c 
     * Atstumas skaiciuojamas pagal haversinusu formule 
     * http://gis-lab.info/qa/great-circles.html
     * http://www.movable-type.co.uk/scripts/LatLong.html
     */
    public int distanceM (GeographicalCoordinates c) {
        double lat1 = inDegree()[0]/180 * Math.PI;
        double lon1 = inDegree()[1]/180 * Math.PI;
        
        double lat2 = c.inDegree()[0]/180 * Math.PI;
        double lon2 = c.inDegree()[1]/180 * Math.PI;
        //Zemes radiusas
        int r = 6372795 ;
        double dlon=lon2-lon1;
        double dlat=lat2-lat1; 
        
        double d = (Math.sin(dlat/2)*Math.sin(dlat/2))+
                   (Math.cos(lat1)*Math.cos(lat2)*
                   (Math.sin(dlon/2)*Math.sin(dlon/2)));
        double angleDif = 2 * Math.atan(Math.sqrt(d) * Math.sqrt(1-d)); 
        return (int)(Math.round(angleDif  * r));
    }
}
